﻿// Learn more about F# at http://fsharp.net


let partition n step coll =
    let rec split ss =
        seq {
            yield(ss |> Seq.truncate n)
            if ss |> Seq.truncate (step+1) |> Seq.length > step then
                yield! split <| (ss |> Seq.skip step)
            }
    split coll

// http://stackoverflow.com/questions/7509863/most-idiomatic-way-to-write-batchesof-size-seq-in-f/7516767#7516767
let chunks size (items:seq<_>) =
    use e = items.GetEnumerator()
    let rec loop i acc =
        seq {
            if i = size then
                yield (List.rev acc)
                yield! loop 0 []
            elif e.MoveNext() then
                yield! loop (i+1) (e.Current::acc)
            else
                yield (List.rev acc)
        }
    if size = 0 then invalidArg "size" "must be greater than zero"
    if Seq.isEmpty items then Seq.empty else loop 0 []
    
let s = Seq.init 10 id
chunks 3 s

// http://stackoverflow.com/questions/7509863/most-idiomatic-way-to-write-batchesof-size-seq-in-f/7510054#7510054
let batchesOf size input =
    let rec loop input num batch acc =
        match input with
        | [] ->
            if batch <> [] then (List.rev batch)::acc else acc
            |> List.rev
        | x::xs when num = size - 1 ->
            loop xs 0 [] ((List.rev (x::batch))::acc)
        | x::xs ->
            loop xs (num + 1) (x::batch) acc
    loop input 0 [] [] 


Seq.initInfinite (fun x -> printfn "Actualizing %d" x; x)

// http://stackoverflow.com/questions/7509863/most-idiomatic-way-to-write-batchesof-size-seq-in-f/7510158#7510158
let batchesOf1 size input =
    input
    |> Seq.mapi (fun i elem -> (i/size),elem)
    |> Seq.groupBy (fun (a,_) -> a)
    |> Seq.map (fun (_,se) -> se |> Seq.map (snd))
 
      
let batchesOf2 n =
    Seq.mapi (fun i v -> i / n, v) >>
    Seq.groupBy fst >>
    Seq.map snd >>
    Seq.map (Seq.map snd)    